package infra

import (
	"context"
	"douhu_backend/internal/config"
	"douhu_backend/internal/dao"
	"douhu_backend/internal/dao/tidb"
	"douhu_backend/internal/infra/database"
	"douhu_backend/internal/infra/logger"
	authModel "douhu_backend/internal/model/auth"
	douyinModel "douhu_backend/internal/model/douyin"
	"douhu_backend/internal/router"
	"douhu_backend/internal/services"
	"fmt"
	"net/http"
	"time"

	"github.com/kataras/iris/v12"
)

var (
	httpServer     *http.Server
	daoManager     *dao.Manager
	serviceManager *services.Manager
)

// Init 初始化所有基础设施和应用
// 调用顺序：Config -> Logger -> Database -> DAO -> Services -> HTTP Server
func Init() error {
	// 1. 初始化配置
	if err := config.Init(); err != nil {
		return fmt.Errorf("failed to init config: %w", err)
	}

	// 2. 初始化日志
	if err := logger.Init(); err != nil {
		return fmt.Errorf("failed to init logger: %w", err)
	}
	logger.Info("Logger initialized successfully")

	// 3. 初始化数据库
	if err := database.Init(); err != nil {
		return fmt.Errorf("failed to init database: %w", err)
	}
	logger.Info("Database initialized successfully")

	// 4. 数据库迁移
	if err := autoMigrate(); err != nil {
		return fmt.Errorf("failed to migrate database: %w", err)
	}

	// 5. 注册 DAO 工厂
	dao.RegisterFactory(&dao.DAOFactory{
		CreateAuthDAO:     tidb.NewAuthDAO,
		CreateHomepageDAO: tidb.NewHomepageDAO,
	})

	// 6. 初始化 DAO 管理器
	daoManager = dao.InitManager(database.GetDB())
	logger.Info("DAO manager initialized successfully")

	// 7. 初始化服务管理器
	var err error
	serviceManager, err = services.InitManager(daoManager)
	if err != nil {
		return fmt.Errorf("failed to initialize service manager: %w", err)
	}
	logger.Info("Service manager initialized successfully")

	// 8. 启动 HTTP 服务器
	if err := startHTTPServer(); err != nil {
		return fmt.Errorf("failed to start HTTP server: %w", err)
	}

	logger.Info("All infrastructure and application initialized successfully")
	return nil
}

// autoMigrate 自动迁移数据库
func autoMigrate() error {
	return database.AutoMigrate(
		// Douyin models
		&douyinModel.Profile{},
		&douyinModel.User{},
		&douyinModel.Video{},
		&douyinModel.Download{},
		&douyinModel.HomePage{}, // Legacy table
		// Auth models
		&authModel.User{},
		&authModel.SMSCode{},
		&authModel.LoginAttempt{},
		&authModel.LoginLimit{},
	)
}

// startHTTPServer 启动 HTTP 服务器
func startHTTPServer() error {
	logger.Info("Starting HTTP server...")

	// 创建 Iris 应用
	app := iris.New()

	// 设置公共中间件
	router.SetupCommonMiddleware(app, serviceManager)

	// 设置公共路由
	router.SetupCommonRoutes(app)

	// 初始化公开路由（不需要鉴权）
	if err := router.InitPublicRoutes(app, serviceManager); err != nil {
		return fmt.Errorf("failed to init public routes: %w", err)
	}

	// 初始化业务路由（需要鉴权）
	if err := router.InitAuthRoutes(app, serviceManager); err != nil {
		return fmt.Errorf("failed to init auth routes: %w", err)
	}

	if err := router.InitDouyinRoutes(app, serviceManager); err != nil {
		return fmt.Errorf("failed to init douyin routes: %w", err)
	}

	// 创建 HTTP 服务器实例
	httpServer = &http.Server{
		Handler: app,
		Addr:    ":8000",
	}

	// 在 goroutine 中启动服务器
	go func() {
		logger.Info("HTTP server listening on :8000")
		if err := app.Listen(":8000"); err != nil {
			logger.Errorf("HTTP server error: %v", err)
		}
	}()

	return nil
}

// Close 关闭所有基础设施和应用
func Close() error {
	logger.Info("Starting graceful shutdown...")

	// 1. 关闭 HTTP 服务器
	if httpServer != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
		defer cancel()

		logger.Info("Shutting down HTTP server...")
		if err := httpServer.Shutdown(ctx); err != nil {
			logger.Errorf("HTTP server shutdown error: %v", err)
			// 强制关闭
			if err := httpServer.Close(); err != nil {
				logger.Errorf("HTTP server close error: %v", err)
			}
		} else {
			logger.Info("HTTP server shutdown gracefully")
		}
	}

	// 2. 关闭数据库
	if err := database.Close(); err != nil {
		logger.Errorf("Failed to close database: %v", err)
		return err
	}
	logger.Info("Database closed successfully")

	logger.Info("Graceful shutdown completed")
	return nil
}

// GetDAOManager 获取 DAO 管理器实例
func GetDAOManager() *dao.Manager {
	return daoManager
}

// GetServiceManager 获取服务管理器实例
func GetServiceManager() *services.Manager {
	return serviceManager
}
